package impl

import (
	"go.uber.org/atomic"
	"iron_man_comm/src/goroslib"
	"iron_man_comm/src/tools/log"
	"time"
)

type CheckType int

const (
	CheckTypeHz = iota + 1
	CheckTypeData
)

type SensorType int

const (
	SensorTypeLds                    = iota + 1 //lds
	SensorTypeEdge                              //沿边线激光
	SensorTypeOdom                              //ODOM
	SensorTypeImu                               //IMU
	SensorTypeMotorSpeed                        //电机转速
	SensorTypeRGBOriginImage                    //RGB原始图像
	SensorTypeRGBResampleImage                  //RGB重采样图像
	SensorTypeIrImage                           //红外相机
	SensorTypeBaseDeviceInstallState            //基站外设安装状态
	SensorTypeTaskState                         //基站任务状态
	SensorTypeBatteryInfo                       //电池信息
	SensorTypeMapData                           //地图数据
)

type Mode int

const (
	ModeHz   = iota //帧率模式
	ModeData        //数据模式
)

/**
 * @brief:	传感器检查
 * @author: haitao.lin
 */
type SensorCheck interface {
	Init(node *goroslib.Node, mode Mode)
	Release()
	EnableTimer(enable bool)
	CheckData() error
}

type SensorCheckData struct {
	mode       Mode
	ticker     *time.Ticker
	quitTicker atomic.Bool
	firstTick  bool         //第一次tick
	firstTime  atomic.Int64 //第一次时间，单位：ms
	latestTime int64        //上一次时间，单位：ms
	dataCount  atomic.Int64 //帧数统计
	node       *goroslib.Node
	subscriber *goroslib.Subscriber
}

func (sensor *SensorCheckData) Init(node *goroslib.Node, mode Mode) {
	sensor.node = node
	sensor.mode = mode
	sensor.quitTicker.Store(false)
	sensor.firstTick = true
}

func (sensor *SensorCheckData) Release() {
	if sensor.subscriber != nil {
		sensor.subscriber.Close()
	}
}

func (sensor *SensorCheckData) onTimerTick() {
	currMillSec := time.Now().UnixMilli()
	count := sensor.dataCount.Load()
	totalAverage := float64(1000.0) / (float64(currMillSec-sensor.firstTime.Load()) / float64(count))
	if sensor.firstTick || 0 != count {
		sensor.firstTick = false
		log.Info.Printf("total average rate: %.3f, window: %d", totalAverage, count)
	} else {
		log.Info.Printf("no new messages")
	}

}

func (sensor *SensorCheckData) EnableTimer(enable bool) {
	if enable {
		if sensor.ticker == nil {
			sensor.ticker = time.NewTicker(1 * time.Second)
			go func() {
				for range sensor.ticker.C {
					if sensor.quitTicker.Load() {
						break
					} else {
						sensor.onTimerTick()
					}
				}
			}()
		}
	} else {
		if sensor.ticker != nil {
			sensor.quitTicker.Store(true)
		}
	}
}

func (sensor *SensorCheckData) calcTime() {
	currMillSec := time.Now().UnixMilli()
	if sensor.firstTime.Load() == 0 {
		sensor.firstTime.Store(currMillSec)
	}
	//更新时间

	sensor.latestTime = currMillSec
	sensor.dataCount.Add(1) //计数
}

/**
 * @brief: 	获取传感器检查实例
 * @author: haitao.lin
 */
func GetSensorCheck(sensorType SensorType) SensorCheck {
	switch sensorType {
	case SensorTypeLds:
		sensor := new(CheckLds)
		return sensor
	case SensorTypeEdge:
		sensor := new(CheckEdge)
		return sensor
	case SensorTypeOdom:
		sensor := new(CheckOdom)
		return sensor
	case SensorTypeImu:
		sensor := new(CheckImu)
		return sensor
	case SensorTypeMotorSpeed:
		sensor := new(CheckMotorSpeed)
		return sensor
	case SensorTypeRGBOriginImage:
		sensor := new(CheckRgbOriginImage)
		return sensor
	case SensorTypeRGBResampleImage:
		sensor := new(CheckRgbResampleImage)
		return sensor
	case SensorTypeIrImage:
		sensor := new(CheckIrImage)
		return sensor
	case SensorTypeBaseDeviceInstallState:
		sensor := new(CheckBaseDeviceInstallState)
		return sensor
	case SensorTypeTaskState:
		sensor := new(CheckBaseTaskState)
		return sensor
	case SensorTypeBatteryInfo:
		sensor := new(CheckBattery)
		return sensor
	case SensorTypeMapData:
		sensor := new(CheckHmiMap)
		return sensor
	default:
		log.Error.Printf("no sensor type: %d", sensorType)
		return nil
	}
}
